#include <ctype.h>
#include <iostream>
#include <fstream>
using namespace std;

#include "Symbole.h"

////////////////////////////////////////////////////////////////////////////////
Symbole::Symbole(string s) {
	this->chaine=s;//la chaine de cet objet (s)
	// attention : l'ordre des tests ci-dessous n'est pas innocent !
			if      (s=="")         this->categorie=FINDEFICHIER;		//si s correspond a ""(rien) alors la categorie de l'objet et une fin de fichier
			else if (s[0]='"')		this->categorie=CHAINE;				//si s correspond a un guillemet alors la categorie de l'objet et une chaine de caractere
			else if (s[0]='#')		this->categorie=COMMENTAIRE;		//si s correspond a un # alors la categorie de l'objet et un commentaire
			else if (isdigit(s[0])) this->categorie=ENTIER;				//si s correspond au premier digit de la liste alors la categorie de l'objet et un entier
         else if (isMotCle(s))   this->categorie=MOTCLE;				//si s correspond a un mot clef alors la categorie de l'objet et un mot clef
        	else if (isalpha(s[0])) this->categorie=VARIABLE;			//si s correspond a une lettre alors la categorie de l'objet et une variable
	    	else                    this->categorie=INDEFINI;			//sinon c'est indefini
}

////////////////////////////////////////////////////////////////////////////////cette fonction retourne l'élément du symbole//    
bool Symbole::operator == (string ch) {
	return  this->chaine==ch  //la chaine de cet objet (ch)                              
	       (this->categorie==VARIABLE     && ch=="<VARIABLE>")     ||
	       (this->categorie==COMMENTAIRE  && ch=="<COMMENTAIRE>")  ||
	       (this->categorie==CHAINE       && ch=="<CHAINE>")   		||
	       (this->categorie==ENTIER       && ch=="<ENTIER>")   		||
	       (this->categorie==INDEFINI     && ch=="<INDEFINI>") 		||
	       (this->categorie==FINDEFICHIER && ch=="<FINDEFICHIER>");
}

/////////////////////////////////////////////////////////////////////////////////////////////
bool Symbole::isMotCle(string s) {
	static vector <string> motsCles; // vecteur pour stocker les mots clés du langage
	// si on n'a pas encore chargé les mots clés dans le vecteur, on le fait !
	if (!motsCles.size()) {
		ifstream fichier(FICHIER_MOTS_CLE, ifstream::in);
		while (!fichier.eof()) {
			string mot;
			getline(fichier, mot);
			if (mot!="") { // insertion triée de s dans le vecteur des mots clés
  				vector<string>::iterator it = motsCles.begin();
  				while (it<motsCles.end() && *it < mot) it++;
  				if (it==motsCles.end() || *it != mot) // si pas trouvé...
    					motsCles.insert(it, mot);
			}
		}
		fichier.close();
	}
 	// on recherche  s dans le vecteur des mots clés triés
	unsigned int i;
	for (i=0; i<motsCles.size() && motsCles[i]<s; i++) ;
	return (i<motsCles.size() && motsCles[i]==s);
}

////////////////////////////////////////////////////////////////////////////////////////////
// Attention : cette fonction (operator << ) n'est pas membre de la classe Symbole
ostream & operator <<(ostream & cout, Symbole symb) {
	cout << "Symbole de type ";
	if      (symb.categorie==Symbole::MOTCLE)       	cout << "<MOTCLE>      ";
	else if (symb.categorie==Symbole::VARIABLE)     	cout << "<VARIABLE>    ";
	else if (symb.categorie==Symbole::ENTIER)       	cout << "<ENTIER>      ";
	else if (symb.categorie==Symbole::INDEFINI)     	cout << "<INDEFINI>    ";
	else if (symb.categorie==Symbole::FINDEFICHIER) 	cout << "<FINDEFICHIER>";
	else if (symb.categorie==Symbole::CHAINE)     		cout << "<CHAINE>    ";
	else if (symb.categorie==Symbole::COMMENTAIRE)     cout << "<COMMENTAIRE>    ";
	cout << " : \"" << symb.chaine << "\"" ;
	return cout;
}
